#define SPACE_WIDTH 10
#define Read32(data) (int)(##data[offset++]&0xFF) | ((##data[offset++]&0xFF)<<8) | ((##data[offset++]&0xFF)<<16) | ((##data[offset++]&0xFF)<<24)
#define GetHeadInt32(data) (int)(##data[0]&0xFF) | ((##data[1]&0xFF)<<8) | ((##data[2]&0xFF)<<16) | ((##data[3]&0xFF)<<24)
// #define Read32(data) (int)((##data[offset++]&0xFF)<<24) | ((##data[offset++]&0xFF)<<16) | ((##data[offset++]&0xFF)<<8) | (##data[offset++]&0xFF)
static String[] s_text_strCache = null;
static ASprite sprFont;
static byte[] _char_map = null;

static boolean LoadPack(String pack)
{
	System.out.println(">>>> LoadPack()");
	byte[] _buffer = null;
	int size = 0;
	int nbString = 0;
	int nbPart = 0;
	int[] stringsOffset = null;
	int offset = 0;
	try
	{
		InputStream is = "".getClass().getResourceAsStream(pack);
		size = is.available();
		_buffer = new byte[size];
		is.read(_buffer);
	}
	catch(Exception ex)
	{
		System.err.println(ex.toString());
		return false;
	}
	nbPart = Read32(_buffer);
	System.out.println(">>>> nbPart: "+nbPart);
	byte[][] partBuffer = new byte[nbPart][];
	int[] nbStringPerPart = new int[nbPart];
	int partSize = 0;
	for(int i=0; i<nbPart; i++)
	{
		partSize = Read32(_buffer);
		if(partSize < 0)
			return false;
		partBuffer[i] = new byte[partSize];
		System.arraycopy(_buffer, offset, partBuffer[i], 0, partSize);
		offset += partSize;
		System.out.println("Part "+(i+1)+": "+partSize+"bytes");
		nbStringPerPart[i] = GetHeadInt32(partBuffer[i]);
		nbString += nbStringPerPart[i];
	}
	
	offset = 0;
	s_text_strCache = new String[nbString];
	int k=0;
	for(int i=0; i<nbPart; i++)
	{
		offset = 4;
		stringsOffset = new int[nbStringPerPart[i]+1];
		stringsOffset[0] = 0;
		for(int j=1; j<nbStringPerPart[i]+1; j++)
		{
			stringsOffset[j] = Read32(partBuffer[i]);
		}
		int len = 0;
		offset = 4*(nbStringPerPart[i]+1);
		for(int j=0; j<nbStringPerPart[i]; j++)
		{
			len = stringsOffset[j+1] - stringsOffset[j];
			s_text_strCache[k] = new String(partBuffer[i], stringsOffset[j] + offset, len);
			k++;
		}
	}
	_buffer = null;
	stringsOffset = null;
	partBuffer = null;
	nbStringPerPart = null;
	System.gc();
	for(int i=0; i<nbString; i++)
	{
		System.out.println("-----"+s_text_strCache[i]);
	}
	return true;
}

static boolean CreateStringCache(String textPack)
{
	System.out.println(">>>> CreateStringCache()");
	byte[] _buffer = null;
	int size = 0;
	int nbString = 0;
	int[] stringsOffset = null;
	int offset = 0;
	try
	{
		InputStream is = "".getClass().getResourceAsStream(textPack);
		size = is.available();
		_buffer = new byte[size];
		is.read(_buffer);
	}
	catch(Exception ex)
	{
		return false;
	}
	nbString = Read32(_buffer);
	System.out.println(">>>> nbString: "+nbString);
	if(nbString < 0)
		return false;
	s_text_strCache = new String[nbString];
	stringsOffset = new int[nbString+1];
	stringsOffset[0] = 0;
	for(int i=1; i<nbString+1; i++)
	{
		stringsOffset[i] = Read32(_buffer);
	}
	int len = 0;
	offset = 4*(nbString+1);
	for(int i=0; i<nbString; i++)
	{
		len = stringsOffset[i+1] - stringsOffset[i];
		s_text_strCache[i] = new String(_buffer, stringsOffset[i] + offset, len);
	}
	// len = stringsOffset[nbString-1] - stringsOffset[nbString-2];
	// s_text_strCache[nbString-1] = new String(_buffer, stringsOffset[nbString-1] + offset, len);
	_buffer = null;
	stringsOffset = null;
	System.gc();
	for(int i=0; i<nbString; i++)
	{
		System.out.println("-----"+s_text_strCache[i]);
	}
	return true;
}
static boolean LoadFont(String fontFile, String mapFile)
{
	System.out.println("............ start LoadFont");
	sprFont = new ASprite();
	if(sprFont.LoadSprite(fontFile) == false)
		return false;
	System.gc();
	int size = 0;
	byte[] data = null;
	try
	{
		InputStream is = "".getClass().getResourceAsStream(mapFile);
		size = is.available();
		data = new byte[size];
		is.read(data);
	}
	catch(Exception ex)
	{
		return false;
	}
	_char_map = new byte[256];
	for(int i=0; i<256; i++)
	{
		_char_map[i] = -1;
	}
	for(int i=0; i<size; i++)
	{
		_char_map[data[i]] = (byte)i;	
	}
	System.out.println("............ end LoadFont");
	return true;
}
static int DrawChar(Graphics g, char c, int x, int y)
{
	if(_char_map[c] == -1)
	{
		g.setColor(255,255,0);
		g.drawRect(x+1,y+1,5,10);
		return 5;
	}
	else
	{
		sprFont.PaintModule(g, _char_map[c], x, y);
		return sprFont.GetModuleWidth(_char_map[c]);
	}
}
static void DrawString(Graphics g, String str, int x, int y)
{
	int n = str.length();
	int w=0;
	char c;
	for(int i=0; i<n; i++)
	{
		c = str.charAt(i);
		if(c == ' ')
			w += SPACE_WIDTH;
		else
		{
			w += DrawChar(g, c, x + w, y);
			// w += sprFont.GetModuleWidth(_char_map[c]);
		}
	}
}

static int GetStringWidth(String str)
{
	int w = 0;
	char c;
	for(int i=0; i<str.length(); i++)
	{
		c = str.charAt(i);
		if(c == ' ')
			w += SPACE_WIDTH;
		else if (_char_map[c] == -1)
			w += 5;
		else
			w += sprFont.GetModuleWidth(_char_map[c]);
	}
	return w;
}
static String GetString(int id)
{
	try
	{
		return s_text_strCache[id].toUpperCase();
		// return s_text_strCache[id];
	}
	catch(Exception ex)
	{
		return "--ERROR--";
	}
}